package com.kingmed.kmss.bpmn.flow.helper;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class HistoryHelper {

	@Autowired
	HistoryService historyService;

	public HistoryHelper(HistoryService historyService) {
		super();
		this.historyService = historyService;
	}

	private <T> String getNonNullValue(T v) {
		if (v == null) return "null";
		
		return v.toString();
	}
	public void test(String instanceId) {
		//List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).list();
		
		List<HistoricActivityInstance> activities =
				  historyService.createHistoricActivityInstanceQuery()
				   .processInstanceId(instanceId)
				   //.unfinished()
				  // .finished()
				   .orderByHistoricActivityInstanceEndTime().asc()
				   .list();

				for (HistoricActivityInstance activity : activities) {
				  System.out.println(activity.getActivityName() + ": " + getNonNullValue(activity.getStartTime()) + "/" 
				    + getNonNullValue(activity.getDurationInMillis()) + " milliseconds");
				}
	}
	public HistoricProcessInstance findHistoryByProcessId(String processId) {
		HistoricProcessInstance historicProcessInstance = this.historyService.createHistoricProcessInstanceQuery()
				.processInstanceId(processId).singleResult();

		log.info("findHistoryByProcessId({}) result is {}", processId, historicProcessInstance);
		return historicProcessInstance;
	}

	public HistoricProcessInstance findHistoryByProcessIdWithVariables(String processId) {
		HistoricProcessInstance historicProcessInstance = this.historyService.createHistoricProcessInstanceQuery().includeProcessVariables()
				.processInstanceId(processId).singleResult();

		log.info("findHistoryByProcessId({}) result is {}", processId, historicProcessInstance);
		return historicProcessInstance;
	}

	public HistoricProcessInstance findHistoryByBusinessKey(String businessKey) {

		HistoricProcessInstance historicProcessInstance = this.historyService.createHistoricProcessInstanceQuery()
				.processInstanceBusinessKey(businessKey).singleResult();

		log.info("findHistoryByProcessId({}) result is {}", businessKey, historicProcessInstance);
		return historicProcessInstance;
	}

	public List<HistoricProcessInstance> findHistoryByCategory(String category) {

		List<HistoricProcessInstance> historicProcessList = this.historyService.createHistoricProcessInstanceQuery()
				.processDefinitionCategory(category).list();

		log.info("findHistoryByProcessId({}) result is {}", category, historicProcessList);
		return historicProcessList;
	}

	public boolean isProcessEnd(String processId) {
		boolean isEnd = false;

		HistoricProcessInstance historicProcessInstance = this.findHistoryByProcessId(processId);

		if (historicProcessInstance != null) {
			log.info("Process instance end time: " + historicProcessInstance.getEndTime());
			if (historicProcessInstance.getEndTime() != null) {
				isEnd = true;
				log.info("Process Id<{}> has finished. ", processId);
			}
		}
		if (isEnd == false) {
			log.info("Process Id<{}> is still running.", processId);
		}
		return isEnd;
	}

	public HistoricProcessInstanceQuery createHistoricProcessInstanceQuery() {
		return historyService.createHistoricProcessInstanceQuery();
	}

	public List<HistoricTaskInstance> findHistoricTaskList(String processInstanceId){
		return historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
	}
}
